#!/usr/bin/python3
import cv2 as cv
import os
import socket
import numpy as np
import paho.mqtt.client as mqtt
import hashlib

# MQTT服务器地址和端口号
mqtt_broker = "43.136.77.177"
mqtt_port = 1883

# 创建MQTT客户端实例
client = mqtt.Client(client_id="", clean_session=True, userdata=None, protocol=mqtt.MQTTv311, transport="tcp")
client.connect(mqtt_broker, mqtt_port, 60)
#建立tcp
HOST = '0.0.0.0'
PORT = 5252
# 创建socket对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定主机和端口
s.bind((HOST, PORT))
# 监听连接
s.listen(1)
print('等待连接...')
# 接受连接
client_socket, client_address = s.accept()
print('已连接：', client_address)
# 创建名为face的文件夹，用于保存人脸数据
if not os.path.exists('face'):
    os.mkdir('face')

# 创建空字典用于保存人脸哈希值数据
face_hashes = {}


# 在每一帧数据中进行人脸识别
while (HOST):  # 摄像头开启后执行
    if HOST :
        # 接收图像数据长度
        data_len = client_socket.recv(16)
        data_len = int(data_len.decode().strip())
        print('接收数据理论长度:', data_len)

        # 循环接收图像数据
        buf = b''
        while len(buf) < data_len:
            data = client_socket.recv(data_len - len(buf))
            if not data:
                break
            buf += data

        print('接收完成! 图像数据长度:', len(buf))

        # 将图像数据转换为numpy数组
        np_data = np.frombuffer(buf, dtype=np.uint8)

        # 解码图像数组
        frame = cv.imdecode(np_data, cv.COLOR_RGB2BGR)
        gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)  # 以灰度图的形式读取图像

        # 实例化OpenCV人脸识别的分类器
        face_cascade = cv.CascadeClassifier(r'haarcascade_frontalface_default.xml')
        face_cascade.load(r'haarcascade_frontalface_default.xml')

        # 调用识别人脸
        faceRects = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=3, minSize=(32, 32))

        # 保存人脸哈希值数据
        if cv.waitKey(1) & 0xFF == ord('1'):
            for faceRect in faceRects:
                x, y, w, h = faceRect
                face = gray[y:y + h, x:x + w]
                face = np.ascontiguousarray(face)
                face_hash = hashlib.md5(face).hexdigest()
                face_hashes[face_hash] = face
                print(f"Saved face with hash: {face_hash}")

        # 检查是否匹配已保存的人脸数据，并发送MQTT消息
        for faceRect in faceRects:
            x, y, w, h = faceRect
            face = gray[y:y + h, x:x + w]
            for face_hash, saved_face in face_hashes.items():
                result = cv.matchTemplate(saved_face, face, cv.TM_CCOEFF_NORMED)
                if result.max() > 0.8:
                    client.publish("system", "on")
                    print("Matched face!")
                    break

        # 显示人脸框
        for faceRect in faceRects:
            x, y, w, h = faceRect
            cv.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)

        # cv.imshow("frame", frame)

    if cv.waitKey(1) & 0xFF == ord('q'):
        break

# 释放资源
cap.release()
cv.destroyAllWindows()
